// --------------------------------------------------------------------------------------------------------------------
// <copyright file="WeakEntry.cs" company="Illusion">
//   The MIT License (MIT)
//      
//   Copyright (c) 2014 yohan zhou 
//      
//   Permission is hereby granted, free of charge, to any person obtaining a
//   copy of this software and associated documentation files (the
//   "Software"), to deal in the Software without restriction, including
//   without limitation the rights to use, copy, modify, merge, publish,
//   distribute, sublicense, and/or sell copies of the Software, and to
//   permit persons to whom the Software is furnished to do so, subject to
//   the following conditions:
//      
//   The above copyright notice and this permission notice shall be included
//   in all copies or substantial portions of the Software.
//      
//   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
//   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
//   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
//   IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
//   CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
//   TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
//   SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
// <summary>
//   Represents the source and the target value.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace Illusion.Utility
{
    /// <summary>
    ///     Represents the source and the target value.
    /// </summary>
    internal struct WeakEntry
    {
        #region Fields

        /// <summary>
        ///     The source property.
        /// </summary>
        private readonly string sourceProperty;

        /// <summary>
        ///     The target hash code.
        /// </summary>
        private readonly int targetHashcode;

        /// <summary>
        ///     The target property.
        /// </summary>
        private readonly string targetProperty;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        ///     Initializes a new instance of the <see cref="WeakEntry"/> struct.
        /// </summary>
        /// <param name="sourceProperty">
        ///     The source property.
        /// </param>
        /// <param name="target">
        ///     The target.
        /// </param>
        /// <param name="targetProperty">
        ///     The target property.
        /// </param>
        public WeakEntry(string sourceProperty, object target, string targetProperty)
        {
            this.targetHashcode = target.GetHashCode();
            this.sourceProperty = sourceProperty;
            this.targetProperty = targetProperty;
        }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        ///     Implements the ==.
        /// </summary>
        /// <param name="obj1">
        ///     The object 1.
        /// </param>
        /// <param name="obj2">
        ///     The object 2.
        /// </param>
        /// <returns>
        ///     The result of the operator.
        /// </returns>
        public static bool operator ==(WeakEntry obj1, WeakEntry obj2)
        {
            return obj1.Equals(obj2);
        }

        /// <summary>
        ///     Implements the !=.
        /// </summary>
        /// <param name="obj1">
        ///     The object 1.
        /// </param>
        /// <param name="obj2">
        ///     The object 2.
        /// </param>
        /// <returns>
        ///     The result of the operator.
        /// </returns>
        public static bool operator !=(WeakEntry obj1, WeakEntry obj2)
        {
            return !(obj1 == obj2);
        }

        /// <summary>
        ///     Determines whether the specified <see cref="System.Object"/> is equal to this instance.
        /// </summary>
        /// <param name="obj">
        ///     Another object to compare to.
        /// </param>
        /// <returns>
        ///     <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
        /// </returns>
        public override bool Equals(object obj)
        {
            var entry = (WeakEntry)obj;
            return (this.targetHashcode == entry.targetHashcode) && (this.sourceProperty == entry.sourceProperty)
                   && (this.targetProperty == entry.targetProperty);
        }

        /// <summary>
        ///     Returns a hash code for this instance.
        /// </summary>
        /// <returns>
        ///     A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
        /// </returns>
        public override int GetHashCode()
        {
            unchecked
            {
                int hash = 17;
                hash = hash * 23 + this.targetHashcode;
                hash = hash * 23 + (this.sourceProperty ?? string.Empty).GetHashCode();
                hash = hash * 23 + (this.targetProperty ?? string.Empty).GetHashCode();
                return hash;
            }
        }

        #endregion
    }
}